package com.example.capsule_netty.service;

import com.example.capsule_netty.bean.MessageBean;
import com.example.capsule_netty.bean.UserInfoBean;
import com.example.capsule_netty.global.GlobalThreadPool;
import com.example.capsule_netty.global.UserAndChannelRelevance;
import com.example.capsule_netty.impl.MessageActionImpl;
import com.example.capsule_netty.mapper.UserInfoMapper;
import com.example.capsule_netty.mapper.UserToImeiBeanMapper;
import com.example.capsule_netty.protocol.MessageBeanProtocol;
import com.google.gson.Gson;
import io.netty.channel.Channel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * @Author: zhuzhiming
 * @Date: 2022/5/3 20:06
 */
@Service
public class UserToImeiService {

    @Autowired
    UserToImeiBeanMapper userToImeiBeanMapper;

    @Autowired
    RedisTemplate<String, String> redisTemplate;

    @Resource
    UserInfoMapper userInfoMapper;

    @Autowired
    UserAndChannelRelevance userAndChannelRelevance;

    @Autowired
    MessageActionImpl messageActionImpl;


    public String getUserIdByImei(String imei) {

        if (imei == null || imei.equals("")) {
            return "";
        }

        String userId = redisTemplate.opsForValue().get(imei);

        if (userId != null) {
            signFriendOnline(userId);
            return userId;
        }

        userId = userToImeiBeanMapper.getUserIdByImei(imei);
        if (userId == null) {
            return "";
        }
        signFriendOnline(userId);
        redisTemplate.opsForValue().set(imei, userId, 30, TimeUnit.MINUTES);
        return userId;
    }

    private void signFriendOnline(String userId) {
        CompletableFuture.runAsync(() -> {
            UserInfoBean userInfoBean = userInfoMapper.selectById(userId);

            userInfoBean.setOnlineStatus(1);
            CompletableFuture.runAsync(() -> {

                String userRedisCache = redisTemplate.opsForValue().get(userId);
                if (userRedisCache != null) {
                    redisTemplate.opsForValue().set(userId, new Gson().toJson(userInfoBean), 10, TimeUnit.MINUTES);
                }
                userInfoMapper.updateById(userInfoBean);
            });

            String[] friends = userInfoBean.getFriends().split(",");

            if (friends.length > 20) {
                int step = friends.length / 20;
                for (int i = 0; i < 5; i++) {
                    int finalI = i;
                    GlobalThreadPool.buildThreadPool().execute(new Runnable() {
                        @Override
                        public void run() {
                            for (int j = finalI * step; j < (finalI == 4 ? friends.length : finalI * step + step); j++) {
                                sendOnlineMessage(friends[j], userId);
                            }
                        }
                    });
                }
            } else {
                for (String friendId : friends) {
                    sendOnlineMessage(friendId, userId);
                }
            }
        });

    }

    private void sendOnlineMessage(String friendId, String userId) {
        UserInfoBean userInfoBean = userInfoMapper.selectById(friendId);
        String imei = userInfoBean.getImei();

        Channel channel = userAndChannelRelevance.getChannelFromImei(imei);

        if (channel == null) {
            return;
        }

        MessageBean messageBean = new MessageBean();
        messageBean.setContent("上线");
        messageBean.setStatus(1);
        messageBean.setMsgType(9);
        messageBean.setSenderId(userId);
        messageBean.setOneToOne(true);
        String json = new Gson().toJson(messageBean);
        byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8);
        MessageBeanProtocol messageBeanProtocol = new MessageBeanProtocol();
        messageBeanProtocol.setLen(json.getBytes(StandardCharsets.UTF_8).length);
        messageBeanProtocol.setContent(jsonBytes);

        channel.writeAndFlush(messageBeanProtocol);
    }

}
